﻿using GalaSoft.MvvmLight;
using DaphneProfi.Model;
using GalaSoft.MvvmLight.Command;
using DaphneProfiBase;
using System.Globalization;
using System;
using Tomers.WPF.Localization;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;
using System.IO;
using GameEngine.PDNParser;
using System.Windows;
using DaphneForms;
using DaphneForms.ViewModel;
using MVVMDialogs;
using DaphneControls.ViewModel;
using System.Reflection;
using GameEngine;

namespace DaphneProfi.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// Actually loaded PDN library
        /// </summary>
        private PDNRawGameList _pdnGameList = null;

        private IDialogService _dlgService;

        private CheckersBoardVM _pActiveCheckersBoardVM = null;

        /// <summary>
        /// Initialization
        /// </summary>
        public MainViewModel()
        {
             // create commands
            /////////////////////////////////////////////////////////////////////////////////
            NewGameCommand = new RelayCommand(() => NewGame());
            SetCzech = new RelayCommand(() => SetLanguage(eLanguage.Czech));
            SetEnglish = new RelayCommand(() => SetLanguage(eLanguage.English));
            ShowGamePanel = new RelayCommand(() => ShowPanel(ePanelType.Game));
            ShowTablebasesPanel = new RelayCommand(() => ShowPanel(ePanelType.Tablebases));
            ShowGameLibraryPanel = new RelayCommand(() => ShowPanel(ePanelType.GameLibrary));
            ShowEngineOutputPanel = new RelayCommand(() => ShowPanel(ePanelType.EngineOutput));
            ShowEngineMatchOutputPanel = new RelayCommand(() => ShowPanel(ePanelType.MatchOutput));
            ShowEditorPanel = new RelayCommand(() => ShowPanel(ePanelType.Editor));

            LoadPDNCommand = new RelayCommand( () => LoadPDN());
            SavePDNCommand = new RelayCommand(() => SavePDN());
            ShowPDNGameListCommand = new RelayCommand(() => ShowGameList());
            RunEngineMatchCommand = new RelayCommand(() => RunEngineMatch());
            ManageCBEngineCommand = new RelayCommand(() => ManageCBEngines());
            ShowLibraryInfoCommand = new RelayCommand(() => ShowLibraryInfo());

            ReplayGameCommand = new RelayCommand(() => SendGlobalCommand(Notify.ReplayGame));
            RotateBoardCommand = new RelayCommand(() => SendGlobalCommand(Notify.RotateBoard));
            SwitchPlayerModeCommand = new RelayCommand(() => SendGlobalCommand(Notify.SwitchPlayerMode));
            StartEditModeCommand = new RelayCommand(() => SendGlobalCommand(Notify.StartEditMode));
            AdviceMoveCommand = new RelayCommand(() => SendGlobalCommand(Notify.AdviceMove));
            MoveNowCommand = new RelayCommand(() => SendGlobalCommand(Notify.MoveNow));        

            _dlgService = ServiceLocator.Resolve<IDialogService>();

            // register message for tracking active checkers board
            Messenger.Default.Register<NotificationMessage<CheckersBoardVM>>(this, (nm) =>
                {

                    if (nm.Notification == Notify.SetIsActiveBoard)
                    {
                        _pActiveCheckersBoardVM = nm.Content;
                    }
                });

        }

        #region Commands


        public RelayCommand SetCzech
        { get; set; }

        public RelayCommand SetEnglish
        { get; set; }

        public RelayCommand ShowGamePanel
        { get; set; }

        public RelayCommand ShowTablebasesPanel
        { get; set; }

        public RelayCommand ShowGameLibraryPanel
        { get; set; }

        public RelayCommand ShowEngineOutputPanel
        { get; set; }

        public RelayCommand ShowEngineMatchOutputPanel
        { get; set; }

        public RelayCommand ShowEditorPanel
        { get; set; }

        public RelayCommand NewGameCommand
        { get; set; }

        public RelayCommand LoadPDNCommand
        { get; set; }

        public RelayCommand SavePDNCommand
        { get; set; }

        public RelayCommand ReplayGameCommand
        { get; set; }

        public RelayCommand RotateBoardCommand
        { get; set; }

        public RelayCommand SwitchPlayerModeCommand
        { get; set; }

        public RelayCommand StartEditModeCommand
        { get; set; }

        public RelayCommand AdviceMoveCommand
        { get; set; }

        public RelayCommand MoveNowCommand
        { get; set; }

        public RelayCommand ShowPDNGameListCommand
        { get; set; }

        public RelayCommand RunEngineMatchCommand
        { get; set; }

        public RelayCommand ManageCBEngineCommand
        { get; set; }

        public RelayCommand ShowLibraryInfoCommand
        { get; set; }
            

        #endregion

        /// <summary>
        /// Runs edit mode on active checkers board
        /// </summary>
        private void StartEditMode()
        {
            // send the message
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage(Notify.StartEditMode));
        }

        /// <summary>
        /// Method for setting language
        /// </summary>
        /// <param name="lang"></param>
        private void SetLanguage(eLanguage lang)
        {
            // get culture info
            CultureInfo cultureInfo;
            switch (lang)
            {
                case eLanguage.Czech:
                    cultureInfo = CultureInfo.GetCultureInfo("cs-CZ");
                    break;
                case eLanguage.English:
                    cultureInfo = CultureInfo.GetCultureInfo("en-US");
                    break;
                default:
                    throw new ApplicationException("Unknown language");
            }

            // set the culture info in the resource provider
            LanguageContext.Instance.Culture = cultureInfo;			

            // broadcast message about setting the culture
            Messenger.Default.Send<NotificationMessage<eLanguage>>(
                    new NotificationMessage<eLanguage>(lang, Notify.SettingLanguage));
        }

        /// <summary>
        /// Shows given panel
        /// </summary>
        private void ShowPanel(ePanelType panelType)
        {
            // send the message for show the panel
            Messenger.Default.Send<NotificationMessage<ePanelType>>(
                new NotificationMessage<ePanelType>(panelType, Notify.ShowPanel));
        }

        /// <summary>
        /// Runs the New Game Configuration
        /// </summary>
        private void NewGame()
        {
            // run the new game form
            NewGameFormVM vm = new NewGameFormVM();
            _dlgService.ShowDialog<NewGameForm>(this, vm);
            
            // if OK button clicked
            if (vm.Result == true)
            {
                // send message to create the new game
                Messenger.Default.Send<NotificationMessage<NewGameFormSettings>>(
                    new NotificationMessage<NewGameFormSettings>(this, vm.Settings, Notify.NewGame));
            }
        }

        /// <summary>
        /// Method for loading PDN file to the game library
        /// </summary>
        private void LoadPDN()
        {
            // show open file dialog
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".pdn";
            dlg.Filter = LanguageContext.Instance.Dictionary.Translate<string>("PDNFilter", "Value");
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            if (dlg.ShowDialog() == true)
            {
                // if successful, load the dialog
                FileStream fileStream = new FileStream(dlg.FileName, FileMode.Open);

                // read the file
                PDNRawGameList gameList;
                PDNReader reader = new PDNReader();
                if (reader.ParseFile(fileStream, out gameList) == false)
                {
                    string sCaption = LanguageContext.Instance.Dictionary.Translate<string>("Error", "Value");
                    MessageBox.Show(reader.ErrorMessage, sCaption, MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                fileStream.Close();

                _pdnGameList = gameList;
            }
            else
            {
                return;
            }

            // show the game list in the PDN Library dialog
            PDNGameListVM gameListVM = new PDNGameListVM();
            gameListVM.SetPDNGameList(_pdnGameList);
            _dlgService.ShowDialog<PDNGameList>(this, gameListVM);

            // set the PDN Game Library if it has changed
            _pdnGameList = gameListVM.LoadedGameList;

            // interpret selected game to load
            if (gameListVM.GameToLoad != null)
            {
                // iterpret game
                PDNInterpreter interpreter = new PDNInterpreter();
                GameManager gameManager = interpreter.InterpretGame(gameListVM.GameToLoad);

                // if successful
                if (gameManager != null)
                {
                    // send message to the main window
                    Messenger.Default.Send<NotificationMessage<GameManager>>
                        (new NotificationMessage<GameManager>(gameManager, Notify.OpenGameFromGameList));
                }
            }
        }

        /// <summary>
        /// Method for saving the game library
        /// </summary>
        private void SavePDN()
        {
        //    GameSaveForm frm = new GameSaveForm();
        //    GameSaveFormVM vm = new GameSaveFormVM();
        //    frm.DataContext = vm;
        //    frm.ShowDialog();           

            NewGameForm frm = new NewGameForm();
            NewGameFormVM vm = new NewGameFormVM();
            frm.DataContext = vm;
            frm.ShowDialog();
        }

        /// <summary>
        /// Shows the list of games in the loaded PDN Library
        /// </summary>
        private void ShowGameList()
        {
            if (_pdnGameList == null)
                return;

            // show the game list in the PDN Library dialog
            PDNGameListVM gameListVM = new PDNGameListVM();
            gameListVM.SetPDNGameList(_pdnGameList);
            _dlgService.ShowDialog<PDNGameList>(this, gameListVM);

            // set the PDN Game Library if it has changed
            _pdnGameList = gameListVM.LoadedGameList;

            // interpret selected game to load
            if (gameListVM.GameToLoad != null)
            {
                // iterpret game
                PDNInterpreter interpreter = new PDNInterpreter();
                GameManager gameManager = interpreter.InterpretGame(gameListVM.GameToLoad);

                // if successful
                if (gameManager != null)
                {
                    // send message to the main window
                    Messenger.Default.Send<NotificationMessage<GameManager>>
                        (new NotificationMessage<GameManager>(gameManager, Notify.OpenGameFromGameList));
                }
            }
        }

        /// <summary>
        /// Method for running engine match
        /// </summary>
        private void RunEngineMatch()
        {
            // run engine matchform
            EngineMatchVM vm = new EngineMatchVM();
            _dlgService.ShowDialog<EngineMatchForm>(this, vm);

            // check the result
            if (vm.DialogResult == true)
            {
                // pass to the view to initialize engine match
                Messenger.Default.Send<NotificationMessage<RunMatchSettings>>(
                    new NotificationMessage<RunMatchSettings>(vm.Settings, Notify.RunEngineMatch));
            }
        }

        /// <summary>
        /// Runs Form for CB Engine Management
        /// </summary>
        private void ManageCBEngines()
        {
            CheckersBoardManageFormVM vm = new CheckersBoardManageFormVM();
            _dlgService.ShowDialog<CheckersBoardManageForm>(this, vm);
        }

        /// <summary>
        /// Show library information
        /// </summary>
        private void ShowLibraryInfo()
        {
            // get app path
            string sAppPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            // show licenses dialog
            Licenses form = new Licenses();
            form.Owner = Application.Current.MainWindow;
            form.Load(sAppPath);
            form.ShowDialog();
        }

        /// <summary>
        /// Sends the global command accross the application
        /// </summary>
        private void SendGlobalCommand(string subCommand)
        {
            GlobalCommandInfo info = new GlobalCommandInfo();
            info.SubCommand = subCommand;
            Messenger.Default.Send<NotificationMessage<GlobalCommandInfo>>(
                new NotificationMessage<GlobalCommandInfo>(info, Notify.GlobalCommand));
        }

        public override void Cleanup()
        {
            // Clean up if needed

            base.Cleanup();
        }
    }
}